// package config 声明当前包为config，与config.go同属一个包，共享基础类型（如Config、Matcher）
package config

import (
	"context" // 提供上下文功能，用于控制配置监听的生命周期（取消、超时）
	"fmt"
	"gameServer/core/value"     // 封装配置值，与config.go依赖一致
	"gameServer/errors"         // 自定义错误，处理配置源不存在、索引溢出等错误
	"gameServer/log"            // 日志工具，记录配置加载、解码、合并等过程的日志
	"gameServer/utils/rconv"    // 类型转换工具，用于配置值的类型转换（如interface{}转string）
	"gameServer/utils/rreflect" // 反射工具，用于判断配置内容的类型（如map、slice）
	"math"                      // 数学工具，用于计算监听名称的最大长度（如math.Min）
	"path/filepath"             // 路径处理工具，解析配置文件的扩展名、全路径等
	"reflect"                   // 反射包，用于处理配置内容的动态类型（如判断是否为struct、slice）
	"strconv"                   // 字符串转换工具，用于将配置路径中的数字key转为int（如"db[0]"的0）
	"strings"                   // 字符串处理工具，分割配置路径（如"app.name"分割为["app","name"]）
	"sync"                      // 同步工具，提供互斥锁（Mutex）、读写锁（RWMutex）保证并发安全
	"sync/atomic"               // 原子操作工具，用于更新配置双缓冲的索引（保证并发读写安全）

	"dario.cat/mergo"          // 配置合并工具，用于合并多个配置源的配置（支持覆盖）
	"github.com/jinzhu/copier" // 深拷贝工具，用于复制配置值（避免浅拷贝导致的并发问题）
)

/* //* 配置管理器实现，聚合多个配置源，支持按优先级获取配置，提供统一的配置操作接口，解决多配置源场景的配置聚合与优先级管理问题 */

/*
组合配置支持
配置管理器（Manager），核心功能是聚合多个配置源（如 FileConfig、EnvConfig），支持按优先级获取配置、
统一设置配置、批量监听配置变化等，解决了多配置源场景下的配置聚合与优先级管理问题

组合配置支持
功能说明：
- 管理多个配置源（如FileConfig、EnvConfig），实现配置聚合
- 支持按优先级获取配置（后添加的配置源优先级更高）
- 提供统一的配置操作接口（获取/设置/监听/加载/保存）
- 支持动态添加/移除配置源、调整优先级
*/

// ConfigManager 配置管理器接口，定义配置管理的完整契约
// 作用：抽象“多配置源聚合管理”的行为，包含配置的检测、获取、设置、监听、加载、保存、关闭
type ConfigManager interface {
	// Has 检测单个匹配规则是否存在配置
	// 参数：pattern string  匹配模式，其实就是 a=b之类的，键值对式的策略
	// 返回值：bool - 存在返回true，不存在返回false
	Has(pattern string) bool

	// Get 获取单个规则的配置值，支持默认值兜底
	// 参数：pattern string - 配置路径规则；def ...interface{} - 可变参数，默认值
	// 返回值：value.Value - 封装后的配置值（实际值或默认值）
	Get(pattern string, def ...interface{}) value.Value

	// Set 设置单个规则的配置值
	// 参数：pattern string - 配置路径规则；value interface{} - 待设置的配置值
	// 返回值：error - 设置成功返回nil，失败（如路径无效）返回错误
	Set(pattern string, value interface{}) error

	// Match 创建多规则匹配器
	// 参数：patterns ...string - 多个配置路径规则
	// 返回值：Matcher - 多规则匹配器实例，可调用Has、Get、Scan方法
	Match(patterns ...string) Matcher

	// Watch 设置配置变化监听回调
	// 参数：wtf WatchCallbackFunc - 配置变化时的回调函数；names ...string - 要监听的配置名称
	Watch(wtf WatchCallbackFunc, names ...string)

	// Load 加载指定配置源的配置文件
	// 参数：ctx context.Context - 上下文；source string - 配置源名称；filesource ...string - 待加载的文件名（可变）
	// 返回值：[]*Config - 加载的配置文件列表；error - 加载失败返回错误
	Load(ctx context.Context, source string, file ...string) ([]*Config, error)

	// Store 保存配置内容到指定配置源的文件
	// 参数：ctx context.Context - 上下文；source string - 配置源名称；filesource string - 目标文件名；
	//      content interface{} - 待保存的配置内容；override ...bool - 是否覆盖原文件（默认不覆盖）
	// 返回值：error - 保存成功返回nil，失败返回错误
	Store(ctx context.Context, source string, file string, content interface{}, override ...bool) error

	// Close 关闭配置管理器，停止所有配置监听
	Close()
}

// WatchCallbackFunc 配置变化监听的回调函数类型
// 参数：names ...string - 发生变化的配置名称列表
type WatchCallbackFunc func(names ...string)

// watcher 配置监听者结构体，存储监听规则与回调
// 作用：管理单个监听任务的“监听范围”（names）和“触发动作”（callback）
type watcher struct {
	names    map[string]struct{} // 监听的配置名称集合（用map实现快速存在性判断）
	callback WatchCallbackFunc   // 配置变化时的回调函数
}

// Manager 配置管理器结构体，ConfigManager接口的实现，配置中心的核心
// 作用：聚合多个配置源，实现配置的并发安全管理、动态监听、聚合查询
type Manager struct {
	codec    *codec                    // 编解码器（*codec在其他文件定义）：用于配置内容的编码/解码
	ctx      context.Context           // 上下文：控制管理器生命周期（取消时停止监听）
	cancel   context.CancelFunc        // 上下文取消函数：调用Close()时触发，停止所有监听goroutine
	sources  map[string]ConfigSource   // 配置源集合：key为配置源名称，value为配置源实例（如FileConfig）
	mu       sync.Mutex                // 互斥锁：保证Set操作（修改配置）的并发安全
	index    int64                     // 双缓冲索引：用原子操作更新，实现配置读写的无锁并发（0或1） 更新索引前，可能在写入，写完更新读取索引，读取操作也就更新了，这个用到了原子操作
	values   [2]map[string]interface{} // 配置双缓冲：存储所有配置值，index指向当前可用的缓冲（避免读写冲突） 允许配置的 “读操作” 和 “写操作” 并发执行，避免锁竞争导致的性能损耗
	rw       sync.RWMutex              // 读写锁：保证watchers（监听者列表）的并发安全（多读少写）
	watchers []*watcher                // 监听者列表：存储所有配置监听任务
}

// var _ ConfigManager = &Manager{} 接口实现断言：编译期检查*Manager是否实现了ConfigManager所有方法
// 若未实现所有方法，编译会报错，确保接口实现的完整性
var _ ConfigManager = &Manager{}

// WithSources 添加配置源到编解码器
func WithSources(sources ...ConfigSource) Codec {
	return func(c *codec) {
		c.sources = append(c.sources, sources...)
	}
}

// NewManager 创建配置管理器实例
// 参数：codecs ...Codec - 可变参数，配置编解码器的选项（如WithContext、WithSources）
// 返回值：*Manager - 初始化后的配置管理器指针
func NewManager(codecs ...Codec) *Manager {
	// 1. 初始化默认编解码器
	c := defaultCodec() // defaultCodec()在其他文件定义，返回默认*codec
	for _, codec := range codecs {
		codec(c) // 应用用户传入的编解码器选项（如设置上下文、配置源）
	}

	// 2. 初始化Manager结构体
	manager := &Manager{}
	manager.codec = c
	// 创建带取消功能的上下文，用于控制监听生命周期
	manager.ctx, manager.cancel = context.WithCancel(c.ctx)
	// 初始化监听者列表（空切片）
	manager.watchers = make([]*watcher, 0)

	// 3. 初始化配置源与配置值
	manager.init()
	// 4. 启动配置源监听（监听配置文件变化）
	manager.watch()

	return manager
}

// init 初始化配置源与配置值：加载所有配置源的配置，解码后存入双缓冲
func (m *Manager) init() {
	// 1. 初始化配置源集合（key为配置源名称，避免重复）
	m.sources = make(map[string]ConfigSource, len(m.codec.sources))
	for _, s := range m.codec.sources {
		m.sources[s.Name()] = s // 用配置源的Name()作为key，确保唯一性
	}

	// 2. 加载所有配置源的配置内容
	values := make(map[string]interface{})   // 临时存储所有配置值
	for _, source := range m.codec.sources { // 遍历每个配置源
		// 调用配置源的Load方法加载配置文件（返回[]*Config）
		configs, err := source.Load(m.ctx)
		if err != nil {
			log.Infof("load configure failed: %v", err) // 加载失败记录日志，继续加载其他源
			continue
		}
		log.Info("=============== show config info ===============")
		// 解码每个配置文件的内容
		for _, config := range configs {
			if len(config.Content) <= 0 { // 配置内容为空，跳过
				continue
			}
			// 调用编解码器的decoder解码配置内容（按config.Format选择解析方式）
			value, err := m.codec.decoder(config.Format, config.Content)
			if err != nil {
				// 非“无效格式”错误才记录（避免未知格式的冗余日志）
				if err != errors.ErrInvalidFormat {
					log.Errorf("decode configure failed: %v", err)
				}
				continue
			}

			// 合并配置到根命名空间（支持嵌套map合并）
			if srcMap, ok := value.(map[string]interface{}); ok {
				// 合并嵌套map到根级别
				mergeMaps(values, srcMap)
			} else {
				// 非map类型直接存储
				values[source.Name()] = value
			}
			log.Infof("source: %s, filesource: %s, loaded config: %+v", source.Name(), config.FullPath, value)
		}
	}
	log.Info("=============== config info over ===============")

	// 调试：打印加载的配置值数量
	log.Debugf("[调试] 加载配置总数: %d", len(values))
	for name, val := range values {
		log.Debugf("[调试] 配置键 %s: %+v", name, val)
	}

	// 3. 将加载的配置存入双缓冲
	m.store(values)
}

// 合并两个map，支持嵌套map合并
func mergeMaps(dest, src map[string]interface{}) {
	for k, v := range src {
		// 将键转换为小写，解决大小写不匹配问题
		k = strings.ToLower(k)
		if destVal, exists := dest[k]; exists {
			// 若目标已存在该键，尝试递归合并
			if destMap, destOk := destVal.(map[string]interface{}); destOk {
				if srcMap, srcOk := v.(map[string]interface{}); srcOk {
					mergeMaps(destMap, srcMap)
					continue
				}
			}
		}
		// 不存在或无法合并，直接覆盖
		dest[k] = v
	}
}

// store 将配置值存入双缓冲：用原子操作更新索引，保证并发安全
// 参数：values map[string]interface{} - 待存储的配置集合
func (m *Manager) store(values map[string]interface{}) {
	// 原子操作更新index：当前index+1后取模2（0→1，1→0），指向新缓冲
	index := atomic.AddInt64(&m.index, 1) % int64(len(m.values))
	// 将配置存入新缓冲（旧缓冲仍可被读取，实现“读写分离”）
	m.values[index] = values
}

// copy 深拷贝当前配置值：避免修改配置时影响正在读取的旧缓冲
// 恢复copy()方法签名，返回map和error
func (m *Manager) copy() (map[string]interface{}, error) {
	// 加载当前可用的配置缓冲（通过index获取）
	values := m.load()

	// 深拷贝配置值（避免浅拷贝导致的并发问题）
	copied := make(map[string]interface{})
	if err := copier.Copy(&copied, values); err != nil {
		log.Errorf("配置深拷贝失败: %v", err)
		return nil, err
	}
	return copied, nil
}

// load 加载当前可用的配置缓冲：通过原子索引获取，保证并发读安全
// 返回值：map[string]interface{} - 当前可用的配置集合
func (m *Manager) load() map[string]interface{} {
	// 原子操作读取index，取模2后获取当前缓冲的索引（0或1）
	index := atomic.LoadInt64(&m.index) % int64(len(m.values))
	return m.values[index] // 返回当前缓冲的配置集合
}

// watch 启动所有配置源的监听：为每个配置源启动goroutine，监听配置变化
func (m *Manager) watch() {
	for _, source := range m.codec.sources { // 遍历每个配置源
		// 调用配置源的Watch方法，获取监听实例（返回Watcher接口，支持Next()和Stop()）
		watch, err := source.Watch(m.ctx)
		if err != nil {
			log.Errorf("watch config content change failed: %v", err)
			continue
		}

		// 为当前配置源启动独立goroutine，处理配置变化
		go func() {
			defer watch.Stop() // goroutine退出时停止监听（避免资源泄漏）

			for {
				select {
				case <-m.ctx.Done(): // 上下文被取消（如调用Close()），退出goroutine
					// 上下文是公用一个的，这样才能一起终止
					return
				default: // 上下文未取消，继续监听
				}

				// 阻塞等待配置变化，返回对应源的配置文件列表
				configs, err := watch.Next()
				if err != nil {
					continue // 监听错误（如临时IO错误），跳过继续等待
				}

				// 处理变化的配置：解码并合并
				names := make([]string, 0, len(configs))      // 记录变化的配置名称
				updatedValues := make(map[string]interface{}) // 记录更新的配置值

				// 取出单独的文件信息
				for _, config := range configs {
					if len(config.Content) == 0 { // 配置内容为空，跳过
						continue
					}
					// 解码变化的配置内容
					value, err := m.codec.decoder(config.Format, config.Content)
					if err != nil {
						log.Errorf("decode config content failed: %v", err)
						continue
					}
					names = append(names, config.Name) // 记录变化的配置名称
					updatedValues[config.Name] = value // 记录更新的配置值
				}

				// 合并更新的配置到双缓冲（加锁保证并发安全）（已经算是捕获变量的形状了）
				func() {
					m.rw.Lock()         // 加写锁，避免合并时其他goroutine修改配置
					defer m.rw.Unlock() // 退出时释放锁

					// 深拷贝当前配置（避免修改原缓冲）
					dest, err := m.copy()
					if err != nil {
						log.Errorf("copy config content failed: %v", err)
						return
					}

					// 合并更新的配置到拷贝后的集合（mergo.WithOverride：新值覆盖旧值）
					err = mergo.Merge(&dest, updatedValues, mergo.WithOverride)
					if err != nil {
						log.Errorf("merge config content failed: %v", err)
						return
					}

					// 将合并后的配置存入双缓冲（更新index指向新缓冲）
					m.store(dest)
				}()

				// 若有配置变化，通知所有监听者
				if len(names) > 0 {
					go m.notify(names...) // 启动goroutine通知，避免阻塞配置更新
				}
			}
		}()
	}
}

// notify 通知所有监听者配置变化：根据监听者关注的配置名称，过滤出有效变化并触发对应回调
// 参数：names ...string - 本次发生变化的配置名称列表（如["app.yaml", "db.json"]）
func (m *Manager) notify(names ...string) {
	// 加读锁：因为仅读取watchers列表（不修改），读锁允许多个goroutine同时读取，提升并发性能
	m.rw.RLock()
	// 延迟释放读锁：函数退出时自动解锁，避免遗忘解锁导致死锁
	defer m.rw.RUnlock()

	// 遍历所有注册的监听者（watchers是存储所有监听任务的切片）
	for _, watch := range m.watchers {
		// watch是单个监听者，包含两个核心字段：
		//   watch.names：监听者关注的配置名称集合（map[string]struct{}类型，用map实现O(1)的存在性判断）
		//   watch.callback：配置变化时的回调函数（WatchCallbackFunc类型）

		// 情况1：监听者未指定关注的名称（watch.names为空）
		// 说明该监听者需要监听"所有配置变化"，直接触发回调并传入所有变化的名称
		if len(watch.names) == 0 {
			watch.callback(names...) // 调用回调，参数为所有变化的配置名称
		} else {
			// 情况2：监听者指定了关注的名称（watch.names有值）
			// 需要过滤出"本次变化的名称"中属于"监听者关注范围"的名称

			// 初始化有效名称切片：
			// 预估容量为"监听者关注的名称数量"和"本次变化的名称数量"中的较小值，减少内存分配
			validNames := make([]string, 0, int(math.Min(float64(len(watch.names)), float64(len(names)))))

			// 遍历本次所有变化的名称，检查是否在监听者的关注范围内
			for _, name := range names {
				// 用map的存在性判断：name是否在watch.names中（O(1)效率）
				if _, ok := watch.names[name]; ok {
					validNames = append(validNames, name) // 加入有效名称列表
				}
			}

			// 若存在有效变化（即有监听者关注的配置发生了变化），触发回调
			if len(validNames) > 0 {
				watch.callback(validNames...) // 传入过滤后的有效名称
			}
		}
	}
}

// Close 关闭配置管理器：停止所有监听，释放资源
func (m *Manager) Close() {
	m.cancel() // 取消上下文，停止所有watch()的goroutine
	// 关闭每个配置源（释放配置源的资源，如文件句柄）
	for _, source := range m.sources {
		_ = source.Close() // 忽略关闭错误（避免资源泄漏即可）
	}
}

// Has 实现ConfigManager接口的Has方法：检测单个规则是否存在配置
// 参数：patterns string - 配置路径规则（例："app.name"）
// 返回值：bool - 存在返回true，不存在返回false
func (m *Manager) Has(patterns string) bool {
	return m.has(patterns) // 调用内部has方法实现逻辑
}

// has 内部方法：实现配置规则的检测逻辑，支持map和slice类型的配置节点
// 参数：patterns string - 配置路径规则（例："db[0].host"→分割为["db","0","host"]）
// 返回值：bool - 存在返回true，不存在返回false
func (m *Manager) has(patterns string) bool {
	keys := strings.Split(patterns, ".")
	values := m.load()
	if values == nil || len(values) == 0 {
		return false
	}

	// 移除reviseKeys调用，直接使用原始键遍历
	// keys = reviseKeys(keys, values)
	var node interface{} = values // 显式声明为interface{}以支持多种类型
	found := true                 // 初始化找到标记为true

	for i, key := range keys {
		log.Debugf("查找第 %d 级键: %s, 当前节点类型: %T", i+1, key, node)
		switch vs := node.(type) {
		case map[string]interface{}:
			if v, ok := vs[key]; ok {
				log.Debugf("找到键 '%s'，值类型: %T", key, v)
				node = v
			} else {
				found = false
			}
		case []interface{}:
			// 处理数组类型：key需为数字索引
			index, err := strconv.Atoi(key)
			if err != nil || index < 0 || index >= len(vs) {
				found = false
			} else {
				node = vs[index]
			}
		default:
			// 当前节点不是map或slice，无法继续遍历
			found = false
		}
		if !found {
			break
		}
	}

	return found
}

// Get 实现ConfigManager接口的Get方法：获取单个规则的配置值，无匹配则返回默认值
// 参数：pattern string - 配置路径规则；def ...interface{} - 可变参数，默认值
// 返回值：value.Value - 封装后的配置值
func (m *Manager) Get(pattern string, def ...interface{}) value.Value {
	// 调用内部get方法查找配置，找到则返回；未找到则返回默认值
	if val, ok := m.get(pattern); ok {
		return val
	}
	return value.NewValue(def...)
}

// get 内部方法：实现配置值的获取逻辑，与has方法逻辑类似，但返回找到的配置值
// 参数：pattern string - 配置路径规则
// 返回值：value.Value - 找到的配置值；bool - 是否找到（true=找到，false=未找到）
func (m *Manager) get(pattern string) (value.Value, bool) {
	keys := strings.Split(pattern, ".")
	values := m.load()
	if values == nil || len(values) == 0 {
		return value.NewValue(), false
	}

	// 移除reviseKeys调用，直接使用原始键遍历
	// keys = reviseKeys(keys, values)
	var node interface{} = values // 显式声明为interface{}以支持多种类型

	// 添加调试日志，追踪键查找过程
	log.Debugf("开始查找配置键: %s, 拆分后键列表: %v", pattern, keys)

	for i, key := range keys {
		log.Debugf("查找第 %d 级键: %s, 当前节点类型: %T", i+1, key, node)
		switch vs := node.(type) {
		case map[string]interface{}:
			if v, ok := vs[key]; ok {
				log.Debugf("找到键 '%s'，值类型: %T", key, v)
				// 类型断言为map或slice以继续遍历
				switch val := v.(type) {
				case map[string]interface{}:
					node = val
				case []interface{}:
					node = val
				default:
					// 叶子节点直接返回
					log.Debugf("到达叶子节点，值: %v", val)
					return value.NewValue(val), true
				}
			} else {
				log.Debugf("未找到键 '%s' 在当前节点", key)
				return value.NewValue(), false
			}
		case []interface{}:
			// 处理数组类型：key需为数字索引
			index, err := strconv.Atoi(key)
			if err != nil || index < 0 || index >= len(vs) {
				log.Debugf("数组索引无效: key=%s, 错误=%v, 数组长度=%d", key, err, len(vs))
				return value.NewValue(), false
			} else {
				node = vs[index]
				log.Debugf("数组索引 %d 对应值类型: %T", index, node)
			}
		default:
			// 当前节点不是map或slice，无法继续遍历
			log.Debugf("当前节点不是map或数组，无法继续查找: 键=%s, 节点类型=%T", key, node)
			return value.NewValue(), false
		}
	}

	log.Debugf("成功找到配置键 '%s'，值: %+v", pattern, node)
	return value.NewValue(node), true
}

// Match 实现ConfigManager接口的Match方法：创建多规则匹配器
// 参数：patterns ...string - 多个配置路径规则
// 返回值：Matcher - 多规则匹配器实例
func (m *Manager) Match(patterns ...string) Matcher {
	// 初始化matcher，传入当前manager和规则列表，返回Matcher接口
	return &matcher{
		manager:  m,
		patterns: patterns,
	}
}

// Set 实现ConfigManager接口的Set方法：设置单个规则的配置值，支持嵌套节点
// 参数：pattern string - 配置路径规则；value interface{} - 待设置的配置值
// 返回值：error - 设置成功返回nil，失败返回错误
func (m *Manager) Set(pattern string, value interface{}) error {
	var (
		keys = strings.Split(pattern, ".") // 分割配置规则为key列表
		node interface{}                   // 当前配置节点
	)

	m.mu.Lock()         // 加互斥锁，保证设置操作的并发安全（同一时间只有一个goroutine修改）
	defer m.mu.Unlock() // 退出时释放锁

	// 深拷贝当前配置（避免修改原缓冲，保证读取的一致性）
	values, err := m.copy()
	if err != nil {
		return err
	}

	// 修正keys，处理组合key
	keys = reviseKeys(keys, values)
	node = values // 初始节点为整个配置集合

	// 遍历每个key，逐层创建/更新配置节点（最后一个key为目标节点）
	for i, key := range keys {
		switch vs := node.(type) {
		// 情况1：当前节点   是map[string]interface{}
		case map[string]interface{}:

			//	若下一个 key 是字符串（如"b"）→ 下一层节点必须是map[string]interface{}（才能通过字符串 key 访问）。
			//若下一个 key 是数字（如"0"）→ 下一层节点必须是[]interface{}（才能通过索引访问）。

			// 子情况1.1：当前key是最后一个（目标节点），直接设置值
			if i == len(keys)-1 {
				vs[key] = value
			} else {
				// 子情况1.2：当前key不是最后一个，需处理下一层节点
				rebuild := false // 是否需要重建下一层节点（如原节点类型不匹配）
				// 尝试将下一个key转为int（判断下一层是slice还是map）
				nextKeyIsInt, err := strconv.Atoi(keys[i+1])

				// 检查当前key是否已存在于map中
				if nextNode, ok := vs[key]; ok {
					// 根据下一个key的类型，判断当前节点类型是否匹配
					switch nextNode.(type) {
					case map[string]interface{}:
						// 下一个key是int（需slice），但当前节点是map，需重建
						rebuild = err == nil
					case []interface{}:
						// 下一个key不是int（需map），但当前节点是slice，需重建
						rebuild = err != nil
						// 下一个key是int且索引溢出，扩展slice长度
						if err == nil && nextKeyIsInt >= len(nextNode.([]interface{})) {
							dest := make([]interface{}, nextKeyIsInt)
							copy(dest, nextNode.([]interface{})) // 拷贝原有元素
							vs[key] = dest                       // 更新当前节点为扩展后的slice
						}
					default:
						// 当前节点是其他类型（如string），无法继续下一层，需重建
						rebuild = true
					}
				} else {
					// 当前key不存在，需新建下一层节点，标记为重建
					rebuild = true
				}

				//当当前节点的类型与下一层 key 所需的类型不匹配时（比如需要 slice 但当前是 map），销毁当前节点
				//创建正确类型的节点（map 或 slice），确保下一层可以继续处理。

				// 重建下一层节点（根据下一个key的类型选择map或slice）
				if rebuild {
					if err != nil {
						// 下一个key不是int，新建map[string]interface{}
						vs[key] = make(map[string]interface{})
					} else {
						// 下一个key是int，新建[]interface{}（初始长度1）
						vs[key] = make([]interface{}, 1)
					}
				}

				// 更新当前节点为下一层节点，继续遍历
				node = vs[key]
			}

		// 情况2：当前节点是[]interface{}
		case []interface{}:
			// 将当前key转为int（作为slice索引）
			index, err := strconv.Atoi(key)
			if err != nil { // key不是数字，无法作为slice索引，返回错误
				return err
			}
			if index >= len(vs) { // 索引溢出，返回错误
				return errors.New("index overflow")
			}

			// 子情况2.1：当前key是最后一个（目标节点），直接设置值
			if i == len(keys)-1 {
				vs[index] = value
			} else {
				// 子情况2.2：当前key不是最后一个，需处理下一层节点
				rebuild := false // 是否需要重建下一层节点
				// 尝试将下一个key转为int
				nextKeyIsInt, err := strconv.Atoi(keys[i+1])

				// 检查当前索引对应的元素是否存在
				currentNode := vs[index]
				switch currentNode.(type) {
				case map[string]interface{}:
					// 下一个key是int（需slice），但当前节点是map，需重建
					rebuild = err == nil
				case []interface{}:
					// 下一个key不是int（需map），但当前节点是slice，需重建
					rebuild = err != nil
					// 下一个key是int且索引溢出，扩展slice长度
					if err == nil && nextKeyIsInt >= len(currentNode.([]interface{})) {
						dest := make([]interface{}, nextKeyIsInt+1)
						copy(dest, currentNode.([]interface{}))
						vs[index] = dest
					}
				default:
					// 当前节点是其他类型，需重建
					rebuild = true
				}

				// 重建下一层节点
				if rebuild {
					if err != nil {
						vs[index] = make(map[string]interface{})
					} else {
						vs[index] = make([]interface{}, 1)
					}
				}

				// 更新当前节点为下一层节点，继续遍历
				node = vs[index]
			}
		}
	}

	// 将修改后的配置存入双缓冲（更新index指向新缓冲）
	m.store(values)
	return nil
}

// Watch 实现ConfigManager接口的Watch方法：添加配置变化监听
// 参数：wtf WatchCallbackFunc - 监听回调函数；names ...string - 要监听的配置名称
func (m *Manager) Watch(wtf WatchCallbackFunc, names ...string) {
	// 初始化监听者
	watch := &watcher{}
	// 初始化监听名称集合（用map实现快速存在性判断）
	watch.names = make(map[string]struct{}, len(names))
	watch.callback = wtf // 绑定回调函数

	// 将监听名称存入map
	for _, name := range names {
		watch.names[name] = struct{}{}
	}

	// 加写锁，保证监听者列表的并发安全（避免添加时其他goroutine读取）
	m.rw.Lock()
	m.watchers = append(m.watchers, watch) // 将监听者添加到列表
	m.rw.Unlock()                          // 释放锁
}

// Load 实现ConfigManager接口的Load方法：加载指定配置源的配置文件
// 参数：ctx context.Context - 上下文；source string - 配置源名称；filesource ...string - 待加载的文件名
// 返回值：[]*Config - 加载的配置文件列表；error - 加载失败返回错误
func (m *Manager) Load(ctx context.Context, configSource string, file ...string) ([]*Config, error) {
	// 查找指定名称的配置源是否存在
	cs, ok := m.sources[configSource]
	if !ok {
		return nil, errors.ErrNotFoundConfigSource // 配置源不存在，返回错误
	}

	// 调用配置源的Load方法加载指定文件（file为可变参数，支持加载多个文件）
	configs, err := cs.Load(ctx, file...)
	if err != nil {
		return nil, err
	}

	// 为每个加载的配置文件设置解码器（使用管理器的全局解码器）
	for _, config := range configs {
		config.decoder = m.codec.decoder
	}

	return configs, nil
}

// Store 实现ConfigManager接口的Store方法：保存配置内容到指定配置源的文件
// 参数：ctx context.Context - 上下文；source string - 配置源名称；filesource string - 目标文件名；
//
//	content interface{} - 待保存的配置内容；override ...bool - 是否覆盖原文件
//
// 返回值：error - 保存成功返回nil，失败返回错误
func (m *Manager) Store(ctx context.Context, configSource string, file string, content interface{}, override ...bool) error {
	if content == nil { // 配置内容为空，返回错误
		return errors.ErrInvalidConfigContent
	}

	// 查找指定名称的配置源是否存在
	cs, ok := m.sources[configSource]
	if !ok {
		return errors.ErrNotFoundConfigSource
	}

	var (
		err error                // 错误变量
		buf []byte               // 待保存的二进制内容
		ext = filepath.Ext(file) // 获取文件扩展名（如".yaml"）
		// 提取文件格式（去掉扩展名的"."，如".yaml"→"yaml"）
		format = strings.TrimPrefix(ext, ".")
	)

	// 根据配置内容的类型，选择不同的编码逻辑
	switch kind, _ := rreflect.Value(content); kind {
	// 情况1：内容是map或struct（需编码为对应格式，如json、yaml）
	case reflect.Map, reflect.Struct:
		// 子情况1.1：需要覆盖原文件（override[0]为true）
		if len(override) > 0 && override[0] {
			// 直接编码内容为二进制
			buf, err = m.codec.encoder(format, content)
		} else {
			// 子情况1.2：不需要覆盖，合并内容到原文件
			// 深拷贝当前配置
			dest, err := m.copy()
			if err != nil {
				return err
			}

			// 提取配置名称（文件名去掉扩展名，如"app.yaml"→"app"）
			name := strings.TrimSuffix(filepath.Base(file), ext)
			// 查找原配置是否存在
			oldVal, ok := dest[name]
			if !ok {
				// 原配置不存在，直接编码新内容
				buf, err = m.codec.encoder(format, content)
			} else if oldMap, ok := oldVal.(map[string]interface{}); ok {
				// 原配置是map，合并新内容到原map
				// 先编码新内容为二进制，再解码为map（统一格式）
				buf, err = m.codec.encoder(format, content)
				if err != nil {
					return err
				}
				newMap, err := m.codec.decoder(format, buf)
				if err != nil {
					return err
				}

				// 合并新map到原map（新值覆盖旧值）
				err = mergo.Merge(&oldMap, newMap, mergo.WithOverride)
				if err != nil {
					return err
				}

				// 编码合并后的map为二进制
				buf, err = m.codec.encoder(format, oldMap)
			} else {
				// 原配置不是map，直接编码新内容（覆盖原内容）
				buf, err = m.codec.encoder(format, content)
			}
		}

	// 情况2：内容是array或slice（直接编码为对应格式）
	case reflect.Array, reflect.Slice:
		buf, err = m.codec.encoder(format, content)

	// 情况3：内容是其他类型（如string、int，转为二进制）
	default:
		// 先转为string，再转为[]byte
		buf = rconv.Bytes(rconv.String(content))
	}

	if err != nil { // 编码失败，返回错误
		return err
	}

	// 调用配置源的Store方法，保存二进制内容到文件
	return cs.Store(ctx, file, buf)
}

// reviseKeys 修正配置key列表：处理组合key（如["app","name"]可能需合并为["app.name"]）
// 作用：解决配置中存在“带.的key”（如"app.name"）时，分割后无法匹配的问题
// 参数：keys []string - 分割后的key列表；values map[string]interface{} - 当前配置集合
// 返回值：[]string - 修正后的key列表
func reviseKeys(keys []string, values map[string]interface{}) []string {
	/*
		大多数情况下，“db.port” 是 “嵌套结构”（需要拆分查找），只有极少数情况是 “顶层 key”（需要直接查找）。
		嵌套就是 db:{port:}这样，直接写出来db.port比较少
		reviseKeys的作用就是自动区分这两种情况。
	*/

	// 从第2个key开始，尝试合并前i+1个key为组合key（如i=1时合并keys[0]和keys[1]）
	for i := 1; i < len(keys); i++ {
		combinedKey := strings.Join(keys[:i+1], ".") // 合并前i+1个key为组合key
		// 检查组合key是否存在于配置中  这里就是看能不能直接找到，直接找到就合并keys里面的两个内容，这里只修正
		// 字符串数组，修正以后给到需要数组的位置
		if _, ok := values[combinedKey]; !ok {
			// 组合key不存在，修正逻辑：
			// 1. 将第0个key设为组合key（如keys[:i+1]）
			keys[0] = combinedKey
			// 2. 将剩余的key（i+1之后）前移，覆盖原有位置
			temp := keys[i+1:]
			copy(keys[i:], temp)
			// 3. 截取修正后的key列表（去掉末尾空元素）
			keys = keys[:len(temp)+1]
			break // 修正一次即可，退出循环
		}
	}
	return keys
}

// matcher结构体实现config.Matcher接口
type matcher struct {
	manager  *Manager
	patterns []string
}

// 自定义通配符匹配函数，支持点分隔键和多级通配符
func matchPattern(pattern, key string) bool {
	// 特殊情况处理：空模式或完全匹配
	if pattern == key || pattern == "*" {
		return true
	}

	patternParts := strings.Split(pattern, ".")
	keyParts := strings.Split(key, ".")

	// 使用动态规划实现通配符匹配
	// dp[i][j] 表示 patternParts[0..i-1] 是否匹配 keyParts[0..j-1]
	lenP, lenK := len(patternParts), len(keyParts)
	dp := make([][]bool, lenP+1)
	for i := range dp {
		dp[i] = make([]bool, lenK+1)
	}
	dp[0][0] = true

	// 处理以*开头的模式
	for i := 1; i <= lenP; i++ {
		if patternParts[i-1] == "*" {
			dp[i][0] = dp[i-1][0]
		}
	}

	// 填充DP表
	for i := 1; i <= lenP; i++ {
		for j := 1; j <= lenK; j++ {
			if patternParts[i-1] == "*" {
				// * 可以匹配0个或多个部分
				dp[i][j] = dp[i-1][j] || dp[i][j-1]
			} else if patternParts[i-1] == "?" || patternParts[i-1] == keyParts[j-1] {
				// ? 匹配单个部分或完全匹配
				dp[i][j] = dp[i-1][j-1]
			}
		}
	}

	return dp[lenP][lenK]
}

// 实现config.Matcher接口的Has方法
func (m *matcher) Has() bool {
	allConfig := m.manager.load()
	results := make(map[string]interface{})
	collectAllKeys(allConfig, "", results)

	for key := range results {
		for _, pattern := range m.patterns {
			if matchPattern(pattern, key) {
				return true
			}
		}
	}
	return false
}

// 实现config.Matcher接口的Get方法
func (m *matcher) Get(def ...interface{}) value.Value {
	allConfig := m.manager.load()
	results := make(map[string]interface{})
	collectAllKeys(allConfig, "", results)

	for key, val := range results {
		for _, pattern := range m.patterns {
			if matchPattern(pattern, key) {
				// 使用value包提供的NewValue构造函数
				return value.NewValue(val)
			}
		}
	}

	if len(def) > 0 {
		return value.NewValue(def[0])
	}
	return value.NewValue(nil)
}

// 实现config.Matcher接口的Scan方法
func (m *matcher) Scan(dest interface{}) error {
	allConfig := m.manager.load()
	results := make(map[string]interface{})
	collectAllKeys(allConfig, "", results)

	matchedResults := make(map[string]interface{})
	for key, value := range results {
		for _, pattern := range m.patterns {
			if matchPattern(pattern, key) {
				matchedResults[key] = value
			}
		}
	}

	// 使用反射将匹配结果设置到目标对象
	rv := reflect.ValueOf(dest).Elem()
	if rv.Kind() == reflect.Map {
		for key, value := range matchedResults {
			rv.SetMapIndex(reflect.ValueOf(key), reflect.ValueOf(value))
		}
	}
	return nil
}

// 递归收集所有配置键，生成点分隔格式
func collectAllKeys(data interface{}, prefix string, results map[string]interface{}) {
	if data == nil {
		return
	}

	switch v := data.(type) {
	case map[string]interface{}:
		for k, val := range v {
			newPrefix := k
			if prefix != "" {
				newPrefix = prefix + "." + k
			}
			collectAllKeys(val, newPrefix, results)
		}
	case []interface{}:
		for i, val := range v {
			newPrefix := fmt.Sprintf("%s[%d]", prefix, i)
			collectAllKeys(val, newPrefix, results)
		}
	default:
		if prefix != "" {
			results[prefix] = data
		}
	}
}
